/*
 * @(#)Criteria.java
 *
 * @author      Orlin Tomov
 * 
 */
package dbu.sql;

import dbu.jdbc.JdbcResultSetMetaData;

public class Criteria {

	private static final String QUOTE = "'";
	private Operator operator;
	private Object a;
	private Object b;

	public static Criteria getCriteria(String expresion) {
		Operator operator = Operator.find(expresion);
		if (operator != null) {
			String a = expresion.substring(0, expresion.indexOf(operator.toString())).trim();
			String b = expresion.substring(expresion.indexOf(operator.toString()) + operator.toString().length()).trim();
			return new Criteria(a, operator, b);
		}
		return null;
	}

	public Criteria(Object a, Operator operator, Object b) {
		this.a = a;
		this.operator = operator;
		this.b = b;
	}

	public Operator getOperator() {
		return operator;
	}

	@SuppressWarnings("unchecked")
	public <A> A getA() {
		return (A) a;
	}

	@SuppressWarnings("unchecked")
	public <B> B getB() {
		return (B) b;
	}

	public boolean evaluate(Object[] bean, JdbcResultSetMetaData meta) {
		switch (operator) {
			case AND: return ((Criteria) a).evaluate(bean, meta) && ((Criteria) b).evaluate(bean, meta);
			case OR: return ((Criteria) a).evaluate(bean, meta) || ((Criteria) b).evaluate(bean, meta);
			case EQ: return evaluateEQ(bean, meta);
			case LIKE: return evaluateLike(bean, meta);
		}
		return false;
	}

	private boolean evaluateEQ(Object[] bean, JdbcResultSetMetaData meta) {
		String value = ((String)b).substring(QUOTE.length(), ((String)b).length() - QUOTE.length()); /** remove quotes */
		return bean[meta.getColumnIndex((String)a)].toString().equalsIgnoreCase(value);
	}

	private boolean evaluateLike(Object[] bean, JdbcResultSetMetaData meta) {
		String value = ((String)b).substring(2, ((String)b).length() - 2); /** remove quotes and % */
		return bean[meta.getColumnIndex((String)a)].toString().toUpperCase().contains(value.toUpperCase());
	}

	@Override
	public String toString() {
		StringBuffer result = new StringBuffer();
		if (getA() instanceof Criteria) {
			Criteria sub = getA();
			result.append(sub.toString());
		} else {
			result.append(getA());
		}
		result.append(operator);
		if (getB() instanceof Criteria) {
			Criteria sub = getB();
			result.append(sub.toString());
		} else {
			result.append(getB());
		}
		return result.toString();
	}
}
